package cluster

import (
	"fmt"
	"kubeInstall/conf"
	"kubeInstall/install"
	"kubeInstall/pkg/client/db"
	"kubeInstall/pkg/logger"
	"kubeInstall/server/models/app"
	"kubeInstall/server/models/cluster"
	"kubeInstall/server/services/host"
	"kubeInstall/server/services/storageplugin"
	"kubeInstall/utils/uuid"
)

func CreateCluster(c *cluster.Cluster) (*cluster.Cluster, error) {
	// 根据host ID 查询对应的vip和api_server,并更新cluster

	c.ID = uuid.GenUUID()
	if err := db.Db.Create(&c).Error; err != nil {
		return nil, err
	}

	// 更新对应的host id 中的cluster ID ,role ,used
	for _, master := range c.MasterNode {
		if err := host.UpdateHostByClusterId(master.ID, c.ID, master.Role); err != nil {
			return nil, err
		}
	}

	for _, worker := range c.WorkerNode {
		if err := host.UpdateHostByClusterId(worker.ID, c.ID, worker.Role); err != nil {
			return nil, err
		}
	}

	if err := storageplugin.UpdateStoragePluginNFSByClusterId(c.StoragePlugin.ID, c.ID); err != nil {
		return nil, err
	}
	return c, nil
}

func UpgradeCluster(clusterId string, c *cluster.Cluster) error {
	return nil
}

func ListClusters(limit, Offset int) ([]cluster.Cluster, error) {
	var clusterList []cluster.Cluster
	if limit == 0 {
		limit = 10
	}
	err := db.Db.Select("*").Limit(limit).Offset((Offset - 1) * limit).Find(&clusterList).Error

	if err != nil {
		return clusterList, err
	}

	return clusterList, nil
}

func GetCluster(clusterId string) (*cluster.Cluster, error) {

	var c cluster.Cluster
	err := db.Db.Where("cluster_id = ?", clusterId).First(&c).Error

	if err != nil {
		if err == db.ErrRecordNotFound {
			return nil, fmt.Errorf("cluster ID %s not found", clusterId)
		}
		return nil, err
	}

	return &c, nil

}

func InitClusterBaseEnv(node cluster.Host, clusterHostNameMap []cluster.HostNameAndIP) error {
	//初始化节点配置
	logger.Info("start to config host %s basic env", node.IP)
	opt := install.NewSshOptions(node)
	h, err := install.NewAsyncHandler(opt)
	if err != nil {
		logger.Error("init ssh client for node %s failed,err %v", node.IP, err)
		return err
	}
	h.ConfigHostName(node.HostName)

	h.ConfigOsBaseEnv()
	for _, ipAndHostName := range clusterHostNameMap {
		h.ConfigClusterHost(ipAndHostName.Ip, ipAndHostName.HostName)
	}
	logger.Info("start to install basic rpm package for host host %s ", node.IP)
	h.InstallBasePkgs(conf.AppSetting.SysPackPath)

	dockerImagePath := conf.AppSetting.MasterDockerImagesPath

	if node.Role == "worker" {
		dockerImagePath = conf.AppSetting.WorkerDockerImagesPath
	}
	logger.Info("start to load docker images for host %s", node.IP)
	h.LoadDockerImages(dockerImagePath)

	return nil
}

func InitMaster0(clusterInfo *cluster.Cluster) (*app.KubeAdmJoinOpts, error) {
	//初始化节点配置

	node0 := clusterInfo.MasterNode[0]
	logger.Info("select %s for as master node", node0.IP)

	masterIps := make([]string, 0)
	for _, m := range clusterInfo.MasterNode {
		masterIps = append(masterIps, m.IP)
	}

	kubeAdmConfig := &app.KubeAdmConfig{
		MasterIPs:   masterIps,
		VIP:         clusterInfo.VipServer,
		Version:     clusterInfo.ClusterVersion,
		ApiServer:   clusterInfo.ApiServer,
		PodCIDR:     clusterInfo.PodCIDR,
		SvcCIDR:     clusterInfo.SvcCIDR,
		RepoName:    clusterInfo.RepoName,
		ProxyMode:   clusterInfo.ProxyMode,
		MaxPodNum:   clusterInfo.MaxPodNum,
		ClusterName: clusterInfo.ClusterName,
		/*		NetworkPlugin:     clusterInfo.NetworkPlugin,
				StoragePluginType: clusterInfo.StoragePluginType,*/
	}
	opt := install.NewSshOptions(node0)
	h, err := install.NewAsyncHandler(opt)
	if err != nil {
		logger.Error("init k8s master node ssh client failed %v", err)
		return nil, err
	}
	joinOpts, err := h.InstallMaster0(kubeAdmConfig)
	if err != nil {
		logger.Error("install k8s master node0 failed %v", err)
	}
	logger.Debug(fmt.Sprintf("init k8s cluster, get join cmd is : %+v", joinOpts))
	return joinOpts, err
}

func AddClusterMasterNode(master cluster.Host, joinOpts *app.KubeAdmJoinOpts) error {
	opt := install.NewSshOptions(master)
	h, err := install.NewAsyncHandler(opt)
	if err != nil {
		logger.Error("init k8s master node ssh client failed %v", err)
		return err
	}

	logger.Debug(fmt.Sprintf("add %s to cluster. join cmd is : %v", master.IP, joinOpts))
	h.JoinK8sMaster(joinOpts)
	return nil
}

func AddClusterWorkerNode(worker cluster.Host, joinOpts *app.KubeAdmJoinOpts) error {
	opt := install.NewSshOptions(worker)
	h, err := install.NewAsyncHandler(opt)
	if err != nil {
		logger.Error("init k8s master node ssh client failed %v", err)
		return err
	}
	logger.Debug(fmt.Sprintf("add %s to cluster. join cmd is : %v", worker.IP, joinOpts))
	h.JoinK8sCluster(joinOpts)
	return nil
}

func InstallApp(app app.AppBuilder, sshHandler *install.AsyncHandler) {

	appyaml := app.ToYaml()
	logger.Debug("Install plugin %s for cluster!app yaml is :%s\n", app.GetAppName(), appyaml)
	sshHandler.InstallApps(app.GetAppName(), appyaml)
}

func InstallNFS(node cluster.Host, serverIp, serverPath string) {
	opt := install.NewSshOptions(node)
	h, err := install.NewAsyncHandler(opt)
	if err != nil {
		logger.Error("init k8s master node ssh client failed %v", err)
	}
	logger.Info("Install NFS plugin for cluster!")
	h.InstallNFS(serverIp, serverPath)
}
